package com.kintreda.ieco_server.module.order.service.impl;

import com.kintreda.ieco_server.bean.account.Organization;
import com.kintreda.ieco_server.bean.account.User;
import com.kintreda.ieco_server.bean.massage.Massage;
import com.kintreda.ieco_server.bean.order.Draw;
import com.kintreda.ieco_server.bean.order.Wallte;
import com.kintreda.ieco_server.bean.user.Statistics;
import com.kintreda.ieco_server.core.repository.IBaseRepository;
import com.kintreda.ieco_server.core.service.impl.BaseServiceImpl;
import com.kintreda.ieco_server.core.web.R;
import com.kintreda.ieco_server.module.account.service.IUserService;
import com.kintreda.ieco_server.module.api.service.IMassageService;
import com.kintreda.ieco_server.module.order.service.IDrawService;
import com.kintreda.ieco_server.module.order.service.IStatisticsService;
import com.kintreda.ieco_server.module.order.service.IWallteService;
import com.kintreda.ieco_server.module.organization.service.IOrganizationService;
import com.kintreda.ieco_server.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Created by IntelliJ IDEA
 * @Project_Name ieco_server
 * @Package com.kintreda.ieco_server.module.order.service.impl
 * @Author ZhongYao_H
 * @Date 2019/4/28:17:10
 * @Year 2019 Month 04 Day 28
 * @Date_zh 2019 年 四月 星期日
 */
@Service
public class StatisticsServiceImpl extends BaseServiceImpl<Statistics,String> implements IStatisticsService {


    @Autowired
    IUserService userService;
    @Autowired
    IBaseRepository<Statistics,String> statisticsRepository;
    @Autowired
    IMassageService massageService;
    @Autowired
    IWallteService wallteService;
    @Autowired
    IOrganizationService organizationService;
    @Autowired
    IDrawService drawService;

    @Override
    public Statistics getByUserId(String userId) {
        List<Statistics> query = query("from Statistics where userId = ?", new Object[]{userId});
        return query.size()>0?query.get(0):null;
    }

    @Override
    public Statistics getByUserIdAndType(String userId, String type) {
        List<Statistics> query = query("from Statistics where userId = ? and type = ? ", new Object[]{userId,type});
        return query.size()>0?query.get(0):null;
    }

    @Override
    public Statistics getByOrgId(String orgId) {
        List<Statistics> query = query("from Statistics where orgId = ?", new Object[]{orgId});
        return query.size()>0?query.get(0):null;
    }

    @Override
    public Statistics getOrgStatistics(String orgId) {
        List<Map<String, Object>> userIdList = statisticsRepository.findListBySql("select id from common_user where orgId = ? ", new String[]{orgId});
        BigDecimal sum = new BigDecimal(0);
        for (Map<String, Object> map : userIdList) {
            String userId = map.get("id").toString();
            Statistics statistics = getByUserIdAndType(userId,"1");
            if (statistics!=null){
                BigDecimal add = statistics.getBalance().add(sum);
                sum = add;
            }
        }
        Statistics statistics = new Statistics();
        statistics.setBalance(sum);
        return statistics;
    }



    @Override
    public synchronized R wallte(String openid, String money, String type, String account, String name, String walletType) throws Exception {


        User user = userService.findUserByOpenId(openid);


        if (StringUtils.equals(walletType,"1")){
        /*个人余额提现*/
            Statistics  statistics = getByUserIdAndType(user.getId(),"0");
            //个人余额
            BigDecimal balance = statistics.getBalance();
            BigDecimal wallteMoney;
            String formalities;
            try {
                wallteMoney = new BigDecimal(money);
                if (wallteMoney.compareTo(new BigDecimal(0))<=0){
                    /*提现金额大于余额*/
                    return R.error("输入合法金额");
                }
            }catch (Exception e){
                return R.error("输入合法金额");
            }

            if (wallteMoney.compareTo(balance)==1){
                /*提现金额大于余额*/
                return R.error("余额不足"+wallteMoney.toString()+",余额"+balance.toString());
            }
            if (wallteMoney.compareTo(new BigDecimal(0)) < 1){
                /*提现金额小于等于0*/
                return R.error("输入合法金额");
            }

            BigDecimal thisBalance = balance.subtract(wallteMoney);
            if (thisBalance.compareTo(new BigDecimal(0))==-1){
                return R.error("余额不足"+wallteMoney.toString()+",余额"+balance.toString()+".");
            }
            BigDecimal formalitie = wallteMoney.multiply(new BigDecimal(0.005));
            formalities = formatToNumber(formalitie) ;
            wallteMoney = wallteMoney.subtract(formalitie);
            statistics.setBalance(thisBalance);
            update(statistics);

            Wallte wallte = new Wallte();
            wallte.setAccount(account);
            wallte.setWallteType(walletType);
            wallte.setName(name);
            wallte.setFormalities(formalities);
            wallte.setStatus("0");
            wallte.setType(type);
            wallte.setStatisticsId(statistics.getId());
            wallte.setOpenId(openid);
            wallte.setUserId(user.getId());
            wallte.setMoney(wallteMoney);
            wallteService.save(wallte);

            Draw draw = new Draw();
            draw.setMoney(new BigDecimal(money));
            draw.setStatisticsId(statistics.getId());
            draw.setWallteId(wallte.getId());
            drawService.save(draw);

            Massage massage = new Massage();
            massage.setTitle("发起个人提现申请");
            massage.setStatus("0");
            massage.setBody(DateUtil.getDate(DateUtil.YYYY_MM_DD_HH_CH)+"发起个人提现申请,金额"+money+"元,手续费:"+formalities+"元");
            massage.setDestination(user.getId());
            massageService.save(massage);
            return R.ok("提交成功,待人工审核后打款");

        }else {
            /*机构余额提现*/
            if (StringUtils.equals(user.getType(),"3")){
                /*机构管理员提现*/

                //机构总余额
                Statistics statistics = getOrgStatistics(user.getOrgId());
                if (statistics==null){
                    return R.error("系统异常!请联系管理员");
                }

                BigDecimal balance = statistics.getBalance();
                BigDecimal wallteMoney;

                try {
                    wallteMoney = new BigDecimal(money);
                    if (wallteMoney.compareTo(new BigDecimal(0))<=0){
                        /*提现金额大于余额*/
                        return R.error("输入合法金额");
                    }
                }catch (Exception e){
                    return R.error("输入合法金额");
                }


                if (wallteMoney.compareTo(balance)==1){
                    /*提现金额大于余额*/
                    return R.error("余额不足提现"+wallteMoney.toString()+",余额"+balance.toString());
                }
                if (wallteMoney.compareTo(new BigDecimal(0)) < 1){
                    /*提现金额小于等于0*/
                    return R.error("输入合法金额");
                }

                BigDecimal formalitie = wallteMoney.multiply(new BigDecimal(0.005));
                BigDecimal finalMoney = wallteMoney.subtract(formalitie);

                        /*减少机构用户的余额*/
                Wallte wallte = new Wallte();
                wallte.setAccount(account);
                wallte.setWallteType(walletType);
                wallte.setName(name);
                wallte.setOpenId(openid);
                wallte.setStatus("0");
                wallte.setType(type);
                wallte.setStatisticsId(statistics.getId());
                wallte.setUserId(user.getId());
                wallte.setMoney(finalMoney);
                wallte.setFormalities(formatToNumber(formalitie));
                wallteService.save(wallte);
                R subtract = subtract(new BigDecimal(money), user.getOrgId(),wallte.getId());

                return subtract;

            }else {
                /*机构用户提现*/
                Organization organization = organizationService.getByAndminId(user.getId());
                if (organization.getAllow()==1){
                    Statistics OrgUserstatistics = getByUserIdAndType(user.getId(), "1");
                    //个人余额
                    BigDecimal balance = OrgUserstatistics.getBalance();
                    BigDecimal wallteMoney;
                    try {
                        wallteMoney = new BigDecimal(money);
                        if (wallteMoney.compareTo(new BigDecimal(0))<=0){
                            /*提现金额大于余额*/
                            return R.error("输入合法金额");
                        }

                    }catch (Exception e){
                        return R.error("输入合法金额");
                    }

                    if (wallteMoney.compareTo(balance)==1){
                        /*提现金额大于余额*/
                        return R.error("余额不足,提现"+wallteMoney.toString()+",余额"+balance.toString());
                    }
                    if (wallteMoney.compareTo(new BigDecimal(0)) < 1){
                        /*提现金额小于等于0*/
                        return R.error("输入合法金额");
                    }

                    BigDecimal thisBalance = balance.subtract(wallteMoney);
                    if (thisBalance.compareTo(new BigDecimal(0))==-1){
                        return R.error("余额不足"+wallteMoney.toString()+",余额."+balance.toString());
                    }

                    BigDecimal formalitie = wallteMoney.multiply(new BigDecimal(0.005));
                    BigDecimal finalMoney = wallteMoney.subtract(formalitie);

                    OrgUserstatistics.setBalance(thisBalance);
                    update(OrgUserstatistics);


                    Massage massage = new Massage();
                    massage.setTitle("发起个人提现申请");
                    massage.setStatus("0");
                    massage.setBody(DateUtil.getDate(DateUtil.YYYY_MM_DD_HH_CH)+"发起机构个人余额提现申请,金额"+money+"元,手续费:"+formatToNumber(formalitie)+"元");
                    massage.setDestination(user.getId());
                    massageService.save(massage);

                    Wallte wallte = new Wallte();
                    wallte.setAccount(account);
                    wallte.setWallteType(walletType);
                    wallte.setName(name);
                    wallte.setType(type);
                    wallte.setFormalities(formatToNumber(formalitie));
                    wallte.setOpenId(openid);
                    wallte.setStatus("0");
                    wallte.setStatisticsId(OrgUserstatistics.getId());
                    wallte.setUserId(user.getId());
                    wallte.setMoney(finalMoney);
                    wallteService.save(wallte);

                    Draw draw = new Draw();
                    draw.setWallteId(wallte.getId());
                    draw.setStatisticsId(OrgUserstatistics.getId());
                    draw.setMoney(new BigDecimal(money));
                    drawService.save(draw);

                    return R.ok("提交成功,待人工审核后打款!");

                }else {
                    return R.error("机构没有开放子机构提现权限!不能提现");
                }


            }

        }


    }



    /**
     * 机构提现减少机构用户的余额
     *
     * */
    @Transactional
    public R subtract(BigDecimal money,String orgId,String wallteId) throws Exception {
        List<Map<String, Object>> userIdList = statisticsRepository.findListBySql("select id from common_user where orgId = ? ", new String[]{orgId});
        //差
        BigDecimal gap = money.add(new BigDecimal(0));
        // 和
        BigDecimal sum = new BigDecimal(0);

        List<Draw> draws = new ArrayList<>();
        List<Massage> massages = new ArrayList<>();
        List<Statistics> statisticss = new ArrayList<>();

        StringBuffer debug =  new StringBuffer();

        for (Map<String, Object> map : userIdList) {
            if (sum.compareTo(money)==0){
                break;
            }


            String userId = map.get("id").toString();
            Statistics statistics = getByUserIdAndType(userId,"1");
            if (statistics!=null){
            BigDecimal userMoney = statistics.getBalance();
            //差对比用户余额 小于取差 大于取于取完
            if (gap.compareTo(userMoney) >= 0){

                statistics.setBalance(new BigDecimal(0));
                BigDecimal add = userMoney.add(sum);
                debug.append(" add= "+add.toString());
                sum = add;
                gap = gap.subtract(userMoney);

                Draw draw = new Draw();
                draw.setMoney(userMoney);
                draw.setStatisticsId(statistics.getId());
                draw.setWallteId(wallteId);
                draws.add(draw);

                Massage massage = new Massage();
                massage.setTitle("机构提现扣款通知");
                massage.setStatus("0");
                massage.setBody(DateUtil.getDate(DateUtil.YYYY_MM_DD_HH_CH)+" 机构管理员发起提现申请,本子机构扣款"+formatToNumber(userMoney)+"元");
                massage.setDestination(userId);
                massages.add(massage);

            }else {

                BigDecimal residue = userMoney.subtract(gap);
                statistics.setBalance(new BigDecimal(formatToNumber(residue)));
                BigDecimal fetch = userMoney.subtract(residue);
                BigDecimal add = fetch.add(sum);
                debug.append("add:"+add.toString());
                gap = gap.subtract(fetch);

                Draw draw = new Draw();
                draw.setWallteId(wallteId);
                draw.setStatisticsId(statistics.getId());
                draw.setMoney(fetch);
                draws.add(draw);

                Massage massage = new Massage();
                massage.setTitle("机构提现扣款通知");
                massage.setStatus("0");
                massage.setBody(DateUtil.getDate(DateUtil.YYYY_MM_DD_HH_CH)+" 机构管理员发起提现申请,本子机构扣款"+formatToNumber(fetch)+"元");
                massage.setDestination(userId);
                massages.add(massage);
            }
            statisticss.add(statistics);
            }
        }
        if (sum.compareTo(money)==0){

            massageService.saveOrUpdateAll(massages);
            drawService.saveOrUpdateAll(draws);
            saveOrUpdateAll(statisticss);

            return R.ok("提交成功,待人工审核后打款!");
        }else if (sum.compareTo(money)==-1){
            return R.error("余额不足! 提现"+money.toString()+"总余额"+sum.toString()+"差"+gap.toString()+debug.toString() );
        }else if(sum.compareTo(money)==1){
            return R.error("系统计算错误!");
        }
        throw new Exception();
    }

    public static String formatToNumber(BigDecimal obj) {
        DecimalFormat df = new DecimalFormat("#.00");
        if(obj.compareTo(BigDecimal.ZERO)==0) {
            return "0.00";
        }else if(obj.compareTo(BigDecimal.ZERO)>0&&obj.compareTo(new BigDecimal(1))<0){
            return "0"+df.format(obj).toString();
        }else {
            return df.format(obj).toString();
        }
    }


}
